package club.jdiy.admin.util;


import club.jdiy.core.ex.JDiyException;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.stream.IntStream;

/**
 * Sec 提供对字符串的加解密.
 *
 * @author ziquee 2014
 */
public class SecUtil {

    public static String sha1(String str) {
        MessageDigest sha;
        try {
            sha = MessageDigest.getInstance("SHA");
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            return "";
        }

        byte[] byteArray = str.getBytes(StandardCharsets.UTF_8);
        byte[] md5Bytes = sha.digest(byteArray);
        StringBuilder hexValue = new StringBuilder();
        IntStream.range(0, md5Bytes.length).map(i -> ((int) md5Bytes[i]) & 0xff).forEach(val -> {
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        });
        return hexValue.toString();
    }

    public static String decrypt(String encrypted) {
        if (encrypted == null || "".equals(encrypted)) return encrypted;
        byte[] tmp = hexStr2ByteArr(encrypted);
        byte[] key = hexStr2ByteArr("1234567890abcdeedcba098765432100");
        try {
            SecretKeySpec sks = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, sks);
            byte[] decrypted = cipher.doFinal(tmp);
            return new String(decrypted);
        } catch (Exception e) {
            throw new JDiyException(e.getMessage());
        }
    }


    public static String ddes(String encrypted, String keys) {
        if (encrypted == null || "".equals(encrypted)) return encrypted;
        byte[] tmp = hexStr2ByteArr(encrypted);
        byte[] key = keys.getBytes();
        try {
            SecretKeySpec sks = new SecretKeySpec(key, "DES");
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.DECRYPT_MODE, sks);
            byte[] decrypted = cipher.doFinal(tmp);
            return new String(decrypted);
        } catch (Exception e) {
            throw new JDiyException(e.getMessage());
        }
    }

    public static String edes(String message, String keys) {
        if (message == null || "".equals(message)) return message;
        byte[] key = keys.getBytes();
        try {
            SecretKeySpec sks = new SecretKeySpec(key, "DES");
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, sks);
            byte[] encrypted = cipher.doFinal(message.getBytes());
            return byteArr2HexStr(encrypted);
        } catch (Exception e) {
            throw new JDiyException(e.getMessage());
        }
    }

    public static String encrypt(String message) {
        if (message == null || "".equals(message)) return message;
        byte[] key = hexStr2ByteArr("1234567890abcdeedcba098765432100");
        try {
            SecretKeySpec sks = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, sks);
            byte[] encrypted = cipher.doFinal(message.getBytes());
            return byteArr2HexStr(encrypted);
        } catch (Exception e) {
            throw new JDiyException(e.getMessage());
        }
    }

    /**
     * Takes the raw bytes from the digest and formats them correct.
     *
     * @param bytes the raw bytes from the digest.
     * @return the formatted bytes.
     */
    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }

    private static String byteArr2HexStr(byte[] buf) {
        StringBuilder sb = new StringBuilder(buf.length * 2);
        int i;
        for (i = 0; i < buf.length; i++) {
            if (((int) buf[i] & 0xff) < 0x10) sb.append("0");
            sb.append(Long.toString((int) buf[i] & 0xff, 16));
        }
        return sb.toString();
    }

    private static byte[] hexStr2ByteArr(String src) {
        if (src.length() < 1) {
            return null;
        }
        byte[] encrypted = new byte[src.length() / 2];
        for (int i = 0; i < src.length() / 2; i++) {
            int high = Integer.parseInt(src.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(src.substring(i * 2 + 1, i * 2 + 2), 16);

            encrypted[i] = (byte) (high * 16 + low);
        }
        return encrypted;
    }

    private SecUtil() {
    }

    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

}
